package org.aphelie.torg.ruler.internal.ui.util;

import java.util.ArrayList;
import java.util.Hashtable;

import org.aphelie.torg.ruler.internal.ui.TGRPluginImages;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;

public class SharedLabelProvider extends LabelProvider {
	
	public static final int F_ERROR = 1;
	public static final int F_WARNING = 2;
	public static final int F_EXPORT = 4;
	public static final int F_EDIT = 8;
	public static final int F_BINARY = 16;
	public static final int F_EXTERNAL = 32;
	public static final int F_JAVA = 64;
	public static final int F_JAR = 128;
	public static final int F_PROJECT = 256;
	public static final int F_OPTIONAL = 512;
	public static final int F_INTERNAL = 1024;
	public static final int F_FRIEND = 2048;
	
	Hashtable images = new Hashtable();
	ArrayList<Object> consumers = new ArrayList<Object>();
	
	public SharedLabelProvider() {
	}
	
	public void connect(Object consumer) {
		if(!consumers.contains(consumer))
			consumers.add(consumer);
	}
	
	public void disconnect(Object consumer) {
		consumers.remove(consumer);
		if (consumers.size() < 1) {
			dispose();
		}
	}
	
	public Image get(ImageDescriptor desc) {
		return get(desc, 0);
	}

	public Image get(ImageDescriptor desc, int flags) {
		Object key = desc;

		if (flags != 0) {
			key = getKey(desc.hashCode(), flags);
		}
		Image image = (Image) images.get(key);
		if (image == null) {
			image = createImage(desc, flags);
			images.put(key, image);
		}
		return image;
	}

	public Image get(Image image, int flags) {
		if (flags == 0)
			return image;
		String key = getKey(image.hashCode(), flags);
		Image resultImage = (Image) images.get(key);
		if (resultImage == null) {
			resultImage = createImage(image, flags);
			images.put(key, resultImage);
		}
		return resultImage;
	}
	
	private String getKey(long hashCode, int flags) {
		return ("" + hashCode) + ":" + flags; //$NON-NLS-1$ //$NON-NLS-2$
	}

	private Image createImage(ImageDescriptor baseDesc, int flags) {
		if (flags == 0) {
			return baseDesc.createImage();
		}
		ImageDescriptor[] lowerLeft = getLowerLeftOverlays(flags);
		ImageDescriptor[] upperRight = getUpperRightOverlays(flags);
		ImageDescriptor[] lowerRight = getLowerRightOverlays(flags);
		ImageDescriptor[] upperLeft = getUpperLeftOverlays(flags);
		OverlayIcon compDesc = new OverlayIcon(baseDesc, new ImageDescriptor[][] {upperRight, lowerRight, lowerLeft, upperLeft});
		return compDesc.createImage();
	}

	private Image createImage(Image baseImage, int flags) {
		if (flags == 0) {
			return baseImage;
		}
		ImageDescriptor[] lowerLeft = getLowerLeftOverlays(flags);
		ImageDescriptor[] upperRight = getUpperRightOverlays(flags);
		ImageDescriptor[] lowerRight = getLowerRightOverlays(flags);
		ImageDescriptor[] upperLeft = getUpperLeftOverlays(flags);
		ImageOverlayIcon compDesc = new ImageOverlayIcon(baseImage, new ImageDescriptor[][] {upperRight, lowerRight, lowerLeft, upperLeft});
		return compDesc.createImage();
	}
	
	private ImageDescriptor[] getLowerLeftOverlays(int flags) {
		if ((flags & F_ERROR) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_ERROR_CO};
		if ((flags & F_WARNING) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_WARNING_CO};
		return null;
	}

	private ImageDescriptor[] getUpperRightOverlays(int flags) {
		if ((flags & F_EXPORT) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_EXPORT_CO};
		if ((flags & F_EDIT) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_DOC_CO};
		if ((flags & F_JAVA) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_JAVA_CO};
		return null;
	}

	private ImageDescriptor[] getLowerRightOverlays(int flags) {
		if ((flags & F_JAR) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_JAR_CO};
		if ((flags & F_PROJECT) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_PROJECT_CO};
		if ((flags & F_OPTIONAL) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_OPTIONAL_CO};
		if ((flags & F_INTERNAL) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_INTERNAL_CO};
		if ((flags & F_FRIEND) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_FRIEND_CO};
		return null;
	}

	private ImageDescriptor[] getUpperLeftOverlays(int flags) {
		if ((flags & F_EXTERNAL) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_EXTERNAL_CO};
		if ((flags & F_BINARY) != 0)
			return new ImageDescriptor[] {TGRPluginImages.DESC_BINARY_CO};
		return null;
	}
	
	
}
